package com.thitech.sif.ws;

import java.net.URL;
import java.rmi.Remote;

import javax.xml.rpc.Service;

import org.apache.axis.client.Stub;

import com.thitech.sif.AbsExecutor;
import com.thitech.sif.Constant;
import com.thitech.sif.ExtendMapKey;
import com.thitech.sif.context.WSContext;
import com.thitech.sif.interceptor.InterceptorExecutor;
import com.thitech.sif.interceptor.InterceptorFactory;
import com.thitech.sif.utils.ReflectRunner;
import com.thitech.sif.utils.StringUtils;
import com.thitech.sif.ws.soap.LogSOAPMessageRPCHandler;
import com.thitech.sif.ws.soap.RPCClientHandlerManager;

/**
 * Web Service 服务执行器
 * 
 * @author shisheng.lian
 * 
 */
public class WsExecutor extends AbsExecutor implements IWSExecutor {

	public WsExecutor(String serviceId, String ticket, String businessId) {
		super(serviceId, ticket, businessId);
	}

	public WsExecutor() {
		super();
	}

	@Override
	public WSBaseOutput execute(WSBaseOutput output, Axis1WSHelper helper) {
		Exception rune = null;
		boolean exeFlag = true;
		try {
			validateInputParam(output, helper);
			exeFlag = InterceptorExecutor.invokeBefore(this);
			this.getExtDataMap().put(ExtendMapKey.BEFORE_INTERCEPTOR_EXECUTE_FLAG, exeFlag);
			if (exeFlag) {
				WSBaseOutput executeOutPut = helper.doExecute(createStub(), this);
				if (null != executeOutPut) {
					output = executeOutPut;
				}
			}
		} catch (Exception e) {
			rune = e;
		} finally {
			try {
				InterceptorExecutor.invokeAfter(this, output, rune);
			} catch (Exception e) {
				InterceptorExecutor.invokeLastFailInterceptor(
						InterceptorFactory.GLOBAL_DEFAULT_EXCEPTION_INTERCEPTOR, this, output, e);
			}
		}
		return output;
	}

	/**
	 * 根据配置文件中提供的服务信息创建Stub
	 * 
	 * @param serviceId
	 * @return
	 * @throws Exception
	 */
	private Remote createStub() throws Exception {
		WSContext context = (WSContext) getContext();
		String wsdlLocation = context.getWSDLLocation();
		int rto = context.getRto();
		String locatorClass = context.getLocatorClass();
		String portName = context.getPortName();
		String userName = context.getUserName();
		String password = context.getPassword();
		
		String soapPortMethodName = "get" + portName;
		

		Class<?> cls = Class.forName(locatorClass);
		Service service = (Service) cls.newInstance();
		RPCClientHandlerManager.registerHandler(service,
				LogSOAPMessageRPCHandler.class);
		Remote soapStub = (Remote) ReflectRunner.getInstance().invokeMethod(
				service, soapPortMethodName,
				new Object[] { new URL(wsdlLocation) },
				new Class[] { URL.class });
		Stub stub = (Stub) soapStub;
		stub.setTimeout(rto);
		if (!StringUtils.isNull(userName)) {
			stub.setUsername(userName);
		}
		if (!StringUtils.isNull(password)) {
			stub.setPassword(password);
		}
		
		return soapStub;
	}

	@Override
	public String getServiceType() {
		return Constant.SERVICE_TYPE_WS;
	}
}
